from datetime import timedelta

from django.db.models import F, Q
from django.utils import timezone
from django_tenants.utils import schema_context
from rest_framework.exceptions import ValidationError

from apps.booking.models import Booking, Appointment
from apps.booking.types import BookingStatusChoices, AppointmentStatusChoices
from apps.location.models import AdminBookingDetails
from apps.users.models import Provider


def cancel_booking(request, booking, recurring_booking=False):
    now = timezone.now()

    if recurring_booking is True:
        if request.provider.cancelation_balance > 0:
            if now - booking.created_at < timedelta(hours=24) \
                    and booking.room is not None:
                # bookings = None
                # if booking.is_recurrent_of is None:
                #     bookings = Booking.objects.filter(Q(id=booking.id) | Q(is_recurrent_of=booking))
                # else:
                #     bookings = Booking.objects.filter(is_recurrent_of=booking.is_recurrent_of,
                #                                       start_date__gte=booking.start_date)

                if booking is not None:
                    booking.status = BookingStatusChoices.CANCELED.value
                    booking.cancel_date = now
                    booking.save()
                if now - booking.created_at < timedelta(hours=1):
                    with schema_context('public'):
                        Provider.objects \
                            .filter(id=request.id) \
                            .update(cancelation_balance=F('cancelation_balance') - 1)

            else:
                raise ValidationError('Booking should at least be created 24 hours before canceling')

        elif booking.room is not None:
            raise ValidationError(
                'You have used all of your cancellation credit for '
                'this month.')

    else:
        if request.provider.cancelation_balance > 0:

            if now - booking.created_at < timedelta(hours=24) \
                    and booking.room is not None:
                if booking is not None:
                    booking.status = BookingStatusChoices.CANCELED.value
                    booking.cancel_date = now
                    booking.save()
                    Appointment.objects.filter(booking=booking).update(status=AppointmentStatusChoices.CANCELLED.value)

                    with schema_context("public"):
                        AdminBookingDetails.objects.filter(id=booking.id).update(
                            status=BookingStatusChoices.CANCELED.value)

                if now - booking.created_at < timedelta(hours=1):

                    with schema_context('public'):
                        Provider.objects \
                            .filter(id=request.id) \
                            .update(cancelation_balance=F('cancelation_balance') - 1)

                        AdminBookingDetails.objects.filter(id=booking.id).update(status=BookingStatusChoices.CANCELED.value)

                # Booking.objects.filter(id=booking.id).update(status=BookingStatusChoices.CANCELED.value,
                #                                              cancel_date=now)
                # Appointment.objects.filter(booking=booking).update(status=AppointmentStatusChoices.CANCELLED.value)

            else:
                raise ValidationError('Booking should at least be created 24 hours before canceling')
        elif booking.room is not None:
            raise ValidationError(
                'You have used all of your cancellation credit for '
                'this month.')